/* 
 *  Incub - incubate your baby robot
 *  Copyright (C) 2008 Stanislaw Szymczyk
 *  e-mail: sszymczy@gmail.com   www: http://cogville.cog-lab.com
 *
 *  This file is part of Incub.
 *
 *  Incub is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  Incub is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Incub.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */
 
#ifndef RENDERER_H_
#define RENDERER_H_

#define GL_GLEXT_PROTOTYPES

#include <map>
#include <vector>
#include <exception>
#include <cstdlib>
#include <GL/glut.h>
#include "World.h"
#include "Shape.h"
#include "Sphere.h"
#include "Cylinder.h"
#include "Capsule.h"
#include "Box.h"
#include "Plane.h"
#include "Light.h"
#include "Camera.h"

class ExitException : public std::exception {
};

class Renderer {
	private:
	static std::map<Entity*, GLuint> displayLists;
	static World *root;
	GLuint framebuffer, depthbuffer, texture;
	static GLuint grayscaleProgram, grayscaleShader;
	static std::vector<Renderer*> renderers;
	static clock_t currTime;
	static int frames;
	static void setShaders();
	static void(*stepFunction)(void);
	static Camera* offscreenCamera;
	Renderer(Camera* cam);
	public:
	void renderEntity(Entity*);
	static void addInstance(Camera* cam);
	static void init(int argc, char **argv, World*, void(*)(void));
	static void activateJoint(Joint* joint);
	static void activateEntity(Entity* entity);
	static void activateSensor(Sensor* sensor);

	static void cleanup();
	static void render_all();
	static void idle();
	private:
	static int win;
	int width, height;
	Camera* camera;
	static void keyb(unsigned char key, int x, int y);
	static void disp(void);
	static void renderOffscreen(void);
	~Renderer();
	static int step;
	static void mouse(int button, int state, int x, int y);
	static void motion (int x, int y);
	static int buttons[5];
	static int cur_x, cur_y;  // for trackball 
	public:
	class RendererException : public std::exception {
		protected: std::string msg;
		public: 
		RendererException(char *m) { msg = std::string(m); }
		virtual const char* what() const throw() { return msg.c_str(); }
		~RendererException () throw () {};
	};
};

#endif /*RENDERER_H_*/
